/* auditd-listen.c -- 
 * Copyright 2008,2009,2011 Red Hat Inc., Durham, North Carolina.
 * All Rights Reserved.
 * Copyright 2012 Nathaniel Husted
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors:
 *   DJ Delorie <dj@redhat.com>
 *   Nathaniel Husted <nhusted@gmail.com>
 * 
 */

#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <ctype.h>
#include <stdlib.h>
#include <netdb.h>
#include <fcntl.h>	/* O_NOFOLLOW needs gnu defined */
#include <libgen.h>
#include <arpa/inet.h>
#include <limits.h>	/* INT_MAX */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

// Used for chown functionality
#include <pwd.h>
#include <grp.h>

#include "libaudit.h"
#include "auditd-event.h"
#include "auditd-config.h"
#include "auditd-parse.h"
#include "private.h"

#include "ev.h"

extern volatile int stop;
extern int send_audit_event(int type, const char *str);
#define AUDITD_SOCKET_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
#define DEFAULT_BUF_SZ  192

typedef struct ev_tcp {
	struct ev_io io;
	struct sockaddr_in addr;
	struct ev_tcp *next, *prev;
	unsigned int bufptr;
	int client_active;
#ifdef USE_GSSAPI
	/* This holds the negotiated security context for this client.  */
	gss_ctx_id_t gss_context;
	char *remote_name;
	int remote_name_len;
#endif
	unsigned char buffer [MAX_AUDIT_MESSAGE_LENGTH + 17];
} ev_tcp;

static int listen_socket;
static struct ev_io tcp_listen_watcher;
static int min_port, max_port, max_per_addr;
static int use_libwrap = 1;
#ifdef USE_GSSAPI
/* This is used to hold our own private key.  */
static gss_cred_id_t server_creds;
static char *my_service_name, *my_gss_realm;
static int use_gss = 0;
static char msgbuf[MAX_AUDIT_MESSAGE_LENGTH + 1];
#endif

static struct ev_tcp *client_chain = NULL;

static char *sockaddr_to_ipv4(struct sockaddr_in *addr)
{
	unsigned char *uaddr = (unsigned char *)&(addr->sin_addr);
	static char buf[40];

	snprintf(buf, sizeof(buf), "%u.%u.%u.%u",
		uaddr[0], uaddr[1], uaddr[2], uaddr[3]);
	return buf;
}

static char *sockaddr_to_addr4(struct sockaddr_in *addr)
{
	unsigned char *uaddr = (unsigned char *)&(addr->sin_addr);
	static char buf[40];

	snprintf(buf, sizeof(buf), "%u.%u.%u.%u:%u",
		uaddr[0], uaddr[1], uaddr[2], uaddr[3],
		ntohs (addr->sin_port));
	return buf;
}

static void set_close_on_exec (int fd)
{
	int flags = fcntl (fd, F_GETFD);
	if (flags == -1)
		flags = 0;
	flags |= FD_CLOEXEC;
	fcntl (fd, F_SETFD, flags);
}

static void release_client(struct ev_tcp *client)
{
	char emsg[DEFAULT_BUF_SZ];

	snprintf(emsg, sizeof(emsg), "addr=%s port=%d res=success",
		sockaddr_to_ipv4(&client->addr), ntohs (client->addr.sin_port));
	send_audit_event(AUDIT_DAEMON_CLOSE, emsg); 
#ifdef USE_GSSAPI
	if (client->remote_name)
		free (client->remote_name);
#endif
	shutdown(client->io.fd, SHUT_RDWR);
	close(client->io.fd);
	if (client_chain == client)
		client_chain = client->next;
	if (client->next)
		client->next->prev = client->prev;
	if (client->prev)
		client->prev->next = client->next;
}

static void close_client(struct ev_tcp *client)
{
	release_client (client);
	free (client);
}

static int ar_write (int sock, const void *buf, int len)
{
	int rc = 0, w;
	while (len > 0) {
		do {
			w = write(sock, buf, len);
		} while (w < 0 && errno == EINTR);
		if (w < 0)
			return w;
		if (w == 0)
			break;
		rc += w;
		len -= w;
		buf = (const void *)((const char *)buf + w);
	}
	return rc;
}

#ifdef USE_GSSAPI
static int ar_read (int sock, void *buf, int len)
{
	int rc = 0, r;
	while (len > 0) {
		do {
			r = read(sock, buf, len);
		} while (r < 0 && errno == EINTR);
		if (r < 0)
			return r;
		if (r == 0)
			break;
		rc += r;
		len -= r;
		buf = (void *)((char *)buf + r);
	}
	return rc;
}


/* Communications under GSS is done by token exchanges.  Each "token"
   may contain a message, perhaps signed, perhaps encrypted.  The
   messages within are what we're interested in, but the network sees
   the tokens.  The protocol we use for transferring tokens is to send
   the length first, four bytes MSB first, then the token data.  We
   return nonzero on error.  */
static int recv_token (int s, gss_buffer_t tok)
{
	int ret;
	unsigned char lenbuf[4];
	unsigned int len;

	ret = ar_read(s, (char *) lenbuf, 4);
	if (ret < 0) {
		audit_msg(LOG_ERR, "GSS-API error reading token length");
		return -1;
	} else if (!ret) {
		return 0;
	} else if (ret != 4) {
		audit_msg(LOG_ERR, "GSS-API error reading token length");
		return -1;
	}

	len = ((lenbuf[0] << 24)
	       | (lenbuf[1] << 16)
	       | (lenbuf[2] << 8)
	       | lenbuf[3]);
	if (len > MAX_AUDIT_MESSAGE_LENGTH) {
		audit_msg(LOG_ERR,
			"GSS-API error: event length excedes MAX_AUDIT_LENGTH");
		return -1;
	}
	tok->length = len;

	tok->value = (char *) malloc(tok->length ? tok->length : 1);
	if (tok->length && tok->value == NULL) {
		audit_msg(LOG_ERR, "Out of memory allocating token data");
		return -1;
	}

	ret = ar_read(s, (char *) tok->value, tok->length);
	if (ret < 0) {
		audit_msg(LOG_ERR, "GSS-API error reading token data");
		free(tok->value);
		return -1;
	} else if (ret != (int) tok->length) {
		audit_msg(LOG_ERR, "GSS-API error reading token data");
		free(tok->value);
		return -1;
	}

	return 1;
}

/* Same here.  */
int send_token(int s, gss_buffer_t tok)
{
	int     ret;
	unsigned char lenbuf[4];
	unsigned int len;

	if (tok->length > 0xffffffffUL)
		return -1;
	len = tok->length;
	lenbuf[0] = (len >> 24) & 0xff;
	lenbuf[1] = (len >> 16) & 0xff;
	lenbuf[2] = (len >> 8) & 0xff;
	lenbuf[3] = len & 0xff;

	ret = ar_write(s, (char *) lenbuf, 4);
	if (ret < 0) {
		audit_msg(LOG_ERR, "GSS-API error sending token length");
		return -1;
	} else if (ret != 4) {
		audit_msg(LOG_ERR, "GSS-API error sending token length");
		return -1;
	}

	ret = ar_write(s, tok->value, tok->length);
	if (ret < 0) {
		audit_msg(LOG_ERR, "GSS-API error sending token data");
		return -1;
	} else if (ret != (int) tok->length) {
		audit_msg(LOG_ERR, "GSS-API error sending token data");
		return -1;
	}

	return 0;
}


static void gss_failure_2 (const char *msg, int status, int type)
{
	OM_uint32 message_context = 0;
	OM_uint32 min_status = 0;
	gss_buffer_desc status_string;

	do {
		gss_display_status (&min_status,
				    status,
				    type,
				    GSS_C_NO_OID,
				    &message_context,
				    &status_string);

		audit_msg (LOG_ERR, "GSS error: %s: %s",
			   msg, (char *)status_string.value);

		gss_release_buffer(&min_status, &status_string);
	} while (message_context != 0);
}

static void gss_failure (const char *msg, int major_status, int minor_status)
{
	gss_failure_2 (msg, major_status, GSS_C_GSS_CODE);
	if (minor_status)
		gss_failure_2 (msg, minor_status, GSS_C_MECH_CODE);
}

#define KCHECK(x,f) if (x) { \
		const char *kstr = krb5_get_error_message(kcontext, x); \
		audit_msg(LOG_ERR, "krb5 error: %s in %s\n", kstr, f); \
		krb5_free_error_message(kcontext, kstr); \
		return -1; }

/* These are our private credentials, which come from a key file on
   our server.  They are aquired once, at program start.  */
static int server_acquire_creds(const char *service_name,
		gss_cred_id_t *server_creds)
{
	gss_buffer_desc name_buf;
	gss_name_t server_name;
	OM_uint32 major_status, minor_status;

	krb5_context kcontext = NULL;
	int krberr;

	my_service_name = strdup (service_name);
	name_buf.value = (char *)service_name;
	name_buf.length = strlen(name_buf.value) + 1;
	major_status = gss_import_name(&minor_status, &name_buf,
				       (gss_OID) gss_nt_service_name,
					&server_name);
	if (major_status != GSS_S_COMPLETE) {
		gss_failure("importing name", major_status, minor_status);
		return -1;
	}

	major_status = gss_acquire_cred(&minor_status,
					server_name, GSS_C_INDEFINITE,
					GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
					server_creds, NULL, NULL);
	if (major_status != GSS_S_COMPLETE) {
		gss_failure("acquiring credentials",
				major_status, minor_status);
		return -1;
	}

	(void) gss_release_name(&minor_status, &server_name);

	krberr = krb5_init_context (&kcontext);
	KCHECK (krberr, "krb5_init_context");
	krberr = krb5_get_default_realm (kcontext, &my_gss_realm);
	KCHECK (krberr, "krb5_get_default_realm");

	audit_msg(LOG_DEBUG, "GSS creds for %s acquired", service_name);

	return 0;
}

/* This is where we negotiate a security context with the client.  In
   the case of Kerberos, this is where the key exchange happens.
   FIXME: While everything else is strictly nonblocking, this
   negotiation blocks.  */
static int negotiate_credentials (ev_tcp *io)
{
	gss_buffer_desc send_tok, recv_tok;
	gss_name_t client;
	OM_uint32 maj_stat, min_stat, acc_sec_min_stat;
	gss_ctx_id_t *context;
	OM_uint32 sess_flags;
	char *slashptr, *atptr;

	context = & io->gss_context;
	*context = GSS_C_NO_CONTEXT;

	maj_stat = GSS_S_CONTINUE_NEEDED;
	do {
		/* STEP 1 - get a token from the client.  */

		if (recv_token(io->io.fd, &recv_tok) <= 0) {
			audit_msg(LOG_ERR,
			"TCP session from %s will be closed, error ignored",
				  sockaddr_to_addr4(&io->addr));
			return -1;
		}
		if (recv_tok.length == 0)
			continue;

		/* STEP 2 - let GSS process that token.  */

		maj_stat = gss_accept_sec_context(&acc_sec_min_stat,
					context, server_creds,
					&recv_tok,
					GSS_C_NO_CHANNEL_BINDINGS, &client,
					NULL, &send_tok, &sess_flags,
					NULL, NULL);
		if (recv_tok.value) {
			free(recv_tok.value);
			recv_tok.value = NULL;
		}
		if (maj_stat != GSS_S_COMPLETE
		    && maj_stat != GSS_S_CONTINUE_NEEDED) {
			gss_release_buffer(&min_stat, &send_tok);
			if (*context != GSS_C_NO_CONTEXT)
				gss_delete_sec_context(&min_stat, context,
					GSS_C_NO_BUFFER);
			gss_failure("accepting context", maj_stat,
				    acc_sec_min_stat);
			return -1;
		}

		/* STEP 3 - send any tokens to the client that GSS may
		   ask us to send.  */

		if (send_tok.length != 0) {
			if (send_token(io->io.fd, &send_tok) < 0) {
				gss_release_buffer(&min_stat, &send_tok);
				audit_msg(LOG_ERR,
			"TCP session from %s will be closed, error ignored",
					  sockaddr_to_addr4(&io->addr));
				if (*context != GSS_C_NO_CONTEXT)
					gss_delete_sec_context(&min_stat,
						context, GSS_C_NO_BUFFER);
				return -1;
			}
			gss_release_buffer(&min_stat, &send_tok);
		}
	} while (maj_stat == GSS_S_CONTINUE_NEEDED);

	maj_stat = gss_display_name(&min_stat, client, &recv_tok, NULL);
	gss_release_name(&min_stat, &client);

	if (maj_stat != GSS_S_COMPLETE) {
		gss_failure("displaying name", maj_stat, min_stat);
		return -1;
	}

	audit_msg(LOG_INFO, "GSS-API Accepted connection from: %s",
		  (char *)recv_tok.value);
	io->remote_name = strdup (recv_tok.value);
	io->remote_name_len = strlen (recv_tok.value);
	gss_release_buffer(&min_stat, &recv_tok);

	slashptr = strchr (io->remote_name, '/');
	atptr = strchr (io->remote_name, '@');

	if (!slashptr || !atptr) {
		audit_msg(LOG_ERR, "Invalid GSS name from remote client: %s",
			  io->remote_name);
		return -1;
	}

	*slashptr = 0;
	if (strcmp (io->remote_name, my_service_name)) {
		audit_msg(LOG_ERR, "Unauthorized GSS client name: %s (not %s)",
			  io->remote_name, my_service_name);
		return -1;
	}
	*slashptr = '/';

	if (strcmp (atptr+1, my_gss_realm)) {
		audit_msg(LOG_ERR, "Unauthorized GSS client realm: %s (not %s)",
			  atptr+1, my_gss_realm);
		return -1;
	}

	return 0;
}
#endif /* USE_GSSAPI */

/* This is called from auditd-event after the message has been logged.
   The header is already filled in.  */
static void client_ack (void *ack_data, const unsigned char *header,
	const char *msg)
{
	ev_tcp *io = (ev_tcp *)ack_data;
#ifdef USE_GSSAPI
	if (use_gss) {
		OM_uint32 major_status, minor_status;
		gss_buffer_desc utok, etok;
		int rc, mlen;

		mlen = strlen (msg);
		utok.length = AUDIT_RMW_HEADER_SIZE + mlen;
		utok.value = malloc (utok.length + 1);

		memcpy (utok.value, header, AUDIT_RMW_HEADER_SIZE);
		memcpy (utok.value+AUDIT_RMW_HEADER_SIZE, msg, mlen);

		/* Wrapping the message creates a token for the
		   client.  Then we just have to worry about sending
		   the token.  */

		major_status = gss_wrap (&minor_status,
					 io->gss_context,
					 1,
					 GSS_C_QOP_DEFAULT,
					 &utok,
					 NULL,
					 &etok);
		if (major_status != GSS_S_COMPLETE) {
			gss_failure("encrypting message", major_status,
					minor_status);
			free (utok.value);
			return;
		}
		// FIXME: What were we going to do with rc?
		rc = send_token (io->io.fd, &etok);
		free (utok.value);
		(void) gss_release_buffer(&minor_status, &etok);

		return;
	}
#endif
	// Send the header and a text error message if it exists
	ar_write (io->io.fd, header, AUDIT_RMW_HEADER_SIZE);
	if (msg[0])
		ar_write (io->io.fd, msg, strlen(msg));
}

static void client_message (struct ev_tcp *io, unsigned int length,
	unsigned char *header)
{
	unsigned char ch;
	uint32_t type, mlen, seq;
	int hver, mver;

	if (AUDIT_RMW_IS_MAGIC (header, length)) {
		AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, mlen, seq)

		ch = header[length];
		header[length] = 0;
		if (length > 1 && header[length-1] == '\n')
			header[length-1] = 0;
		if (type == AUDIT_RMW_TYPE_HEARTBEAT) {
			unsigned char ack[AUDIT_RMW_HEADER_SIZE];
			AUDIT_RMW_PACK_HEADER (ack, 0, AUDIT_RMW_TYPE_ACK,
				0, seq);
			client_ack (io, ack, "");
		} else 
			enqueue_formatted_event(header+AUDIT_RMW_HEADER_SIZE,
				client_ack, io, seq);
		header[length] = ch;
	} else {
		header[length] = 0;
		if (length > 1 && header[length-1] == '\n')
			header[length-1] = 0;
		enqueue_formatted_event (header, NULL, NULL, 0);
	}
}

static void auditd_tcp_client_handler( struct ev_loop *loop,
			struct ev_io *_io, int revents )
{
	struct ev_tcp *io = (struct ev_tcp *) _io;
	int i, r;
	int total_this_call = 0;

	io->client_active = 1;

	/* The socket is non-blocking, but we have a limited buffer
	   size.  In the event that we get a packet that's bigger than
	   our buffer, we need to read it in multiple parts.  Thus, we
	   keep reading/parsing/processing until we run out of ready
	   data.  */
read_more:
	r = read (io->io.fd,
		  io->buffer + io->bufptr,
		  MAX_AUDIT_MESSAGE_LENGTH - io->bufptr);

	if (r < 0 && errno == EAGAIN)
		r = 0;

	/* We need to keep track of the difference between "no data
	 * because it's closed" and "no data because we've read it
	 * all".  */
	if (r == 0 && total_this_call > 0) {
		return;
	}

	/* If the connection is gracefully closed, the first read we
	   try will return zero.  If the connection times out or
	   otherwise fails, the read will return -1.  */
	if (r <= 0) {
		if (r < 0)
			audit_msg (LOG_WARNING,
				"client %s socket closed unexpectedly",
				sockaddr_to_addr4(&io->addr));

		/* There may have been a final message without a LF.  */
		if (io->bufptr) {
			client_message (io, io->bufptr, io->buffer);

		}

		ev_io_stop (loop, _io);
		close_client (io);
		return;
	}

	total_this_call += r;

more_messages:
#ifdef USE_GSSAPI
	/* If we're using GSS at all, everything will be encrypted,
	   one record per token.  */
	if (use_gss) {
		gss_buffer_desc utok, etok;
		io->bufptr += r;
		uint32_t len;
		OM_uint32 major_status, minor_status;

		/* We need at least four bytes to test the length.  If
		   we have more than four bytes, we can tell if we
		   have a whole token (or more).  */

		if (io->bufptr < 4)
			return;

		len = (  ((uint32_t)(io->buffer[0] & 0xFF) << 24)
		       | ((uint32_t)(io->buffer[1] & 0xFF) << 16)
		       | ((uint32_t)(io->buffer[2] & 0xFF) << 8)
		       |  (uint32_t)(io->buffer[3] & 0xFF));

		/* Make sure we got something big enough and not too big */
		if (io->bufptr < 4 + len || len > MAX_AUDIT_MESSAGE_LENGTH)
			return;
		i = len + 4;

		etok.length = len;
		etok.value = io->buffer + 4;

		/* Unwrapping the token gives us the original message,
		   which we know is already a single record.  */
		major_status = gss_unwrap (&minor_status, io->gss_context,
				&etok, &utok, NULL, NULL);

		if (major_status != GSS_S_COMPLETE) {
			gss_failure("decrypting message", major_status,
				minor_status);
		} else {
			/* client_message() wants to NUL terminate it,
			   so copy it to a bigger buffer.  Plus, we
			   want to add our own tag.  */
			memcpy (msgbuf, utok.value, utok.length);
			while (utok.length > 0 && msgbuf[utok.length-1] == '\n')
				utok.length --;
			snprintf (msgbuf + utok.length,
				MAX_AUDIT_MESSAGE_LENGTH - utok.length,
				" krb5=%s", io->remote_name);
			utok.length += 6 + io->remote_name_len;
			client_message (io, utok.length, msgbuf);
			gss_release_buffer(&minor_status, &utok);
		}
	} else
#endif
	if (AUDIT_RMW_IS_MAGIC (io->buffer, (io->bufptr+r))) {
		uint32_t type, len, seq;
		int hver, mver;
		unsigned char *header = (unsigned char *)io->buffer;

		io->bufptr += r;

		if (io->bufptr < AUDIT_RMW_HEADER_SIZE)
			return;

		AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, len, seq);

		/* Make sure len is not too big */
		if (len > MAX_AUDIT_MESSAGE_LENGTH)
			return;

		i = len;
		i += AUDIT_RMW_HEADER_SIZE;

		/* See if we have enough bytes to extract the whole message.  */
		if (io->bufptr < i)
			return;
		
		/* We have an I-byte message in buffer. Send ACK */
		client_message (io, i, io->buffer);

	} else {
		/* At this point, the buffer has IO->BUFPTR+R bytes in it.
		   The first IO->BUFPTR bytes do not have a LF in them (we've
		   already checked), we must check the R new bytes.  */

		for (i = io->bufptr; i < io->bufptr + r; i ++)
			if (io->buffer [i] == '\n')
				break;

		io->bufptr += r;

		/* Check for a partial message, with no LF yet.  */
		if (i == io->bufptr)
			return;

		i++;

		/* We have an I-byte message in buffer. Send ACK */
		client_message (io, i, io->buffer);
	}

	/* Now copy any remaining bytes to the beginning of the
	   buffer.  */
	memmove(io->buffer, io->buffer + i, io->bufptr - i);
	io->bufptr -= i;

	/* See if this packet had more than one message in it. */
	if (io->bufptr > 0) {
		r = io->bufptr;
		io->bufptr = 0;
		goto more_messages;
	}

	/* Go back and see if there's more data to read.  */
	goto read_more;
}

#ifndef HAVE_LIBWRAP
#define auditd_tcpd_check(s) ({ 0; })
#else
int allow_severity = LOG_INFO, deny_severity = LOG_NOTICE;
static int auditd_tcpd_check(int sock)
{
	struct request_info request;

	request_init(&request, RQ_DAEMON, "auditd", RQ_FILE, sock, 0);
	fromhost(&request);
	if (! hosts_access(&request))
		return 1;
	return 0;
}
#endif

/*
 * This function counts the number of concurrent connections and returns
 * a 1 if there are too many and a 0 otherwise. It assumes the incoming
 * connection has not been added to the linked list yet.
 */
static int check_num_connections(struct sockaddr_in *aaddr)
{
	int num = 0;
	struct ev_tcp *client = client_chain;

	while (client) {
		if (memcmp(&aaddr->sin_addr, &client->addr.sin_addr, 
					sizeof(struct in_addr)) == 0) {
			num++;
			if (num > max_per_addr)
				return 1;
		}
		client = client->next;
	}
	return 0;
}

static void auditd_tcp_listen_handler( struct ev_loop *loop,
	struct ev_io *_io, int revents )
{
	int one=1;
	int afd;
	socklen_t aaddrlen;
	struct sockaddr_in aaddr;
	struct ev_tcp *client;
	char emsg[DEFAULT_BUF_SZ];

	/* Accept the connection and see where it's coming from.  */
	aaddrlen = sizeof(aaddr);
	afd = accept (listen_socket, (struct sockaddr *)&aaddr, &aaddrlen);
	if (afd == -1) {
        	audit_msg(LOG_ERR, "Unable to accept TCP connection");
		return;
	}

	/* Make sure we don't have too many connections */
	if (check_num_connections(&aaddr)) {
        	audit_msg(LOG_ERR, "Too many connections from %s - rejected",
				sockaddr_to_addr4(&aaddr));
		snprintf(emsg, sizeof(emsg),
			"op=dup addr=%s port=%d res=no",
			sockaddr_to_ipv4(&aaddr),
			ntohs (aaddr.sin_port));
		send_audit_event(AUDIT_DAEMON_ACCEPT, emsg);
		shutdown(afd, SHUT_RDWR);
		close(afd);
		return;
	}

	/* Connection is accepted...start setting it up */
	setsockopt(afd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (int));
	setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof (int));
	setsockopt(afd, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof (int));
	set_close_on_exec (afd);

	/* Make the client data structure */
	client = (struct ev_tcp *) malloc (sizeof (struct ev_tcp));
	if (client == NULL) {
        	audit_msg(LOG_CRIT, "Unable to allocate TCP client data");
		snprintf(emsg, sizeof(emsg),
			"op=alloc addr=%s port=%d res=no",
			sockaddr_to_ipv4(&aaddr),
			ntohs (aaddr.sin_port));
		send_audit_event(AUDIT_DAEMON_ACCEPT, emsg);
		shutdown(afd, SHUT_RDWR);
		close(afd);
		return;
	}

	memset (client, 0, sizeof (struct ev_tcp));
	client->client_active = 1;

	// Was watching for EV_ERROR, but libev 3.48 took it away
	ev_io_init (&(client->io), auditd_tcp_client_handler, afd, EV_READ);

	memcpy (&client->addr, &aaddr, sizeof (struct sockaddr_in));

#ifdef USE_GSSAPI
	if (use_gss && negotiate_credentials (client)) {
		shutdown(afd, SHUT_RDWR);
		close(afd);
		free(client);
		return;
	}
#endif

	fcntl(afd, F_SETFL, O_NONBLOCK | O_NDELAY);
	ev_io_start (loop, &(client->io));

	/* Add the new connection to a linked list of active clients.  */
	client->next = client_chain;
	if (client->next)
		client->next->prev = client;
	client_chain = client;

	/* And finally log that we accepted the connection */
	snprintf(emsg, sizeof(emsg),
		"addr=%s port=%d res=success", sockaddr_to_ipv4(&aaddr),
		ntohs (aaddr.sin_port));
	send_audit_event(AUDIT_DAEMON_ACCEPT, emsg);
}

void auditd_set_ports(int minp, int maxp, int max_p_addr)
{
	min_port = minp;
	max_port = maxp;
	max_per_addr = max_p_addr;
}

int auditd_tcp_listen_init ( struct ev_loop *loop, struct daemon_conf *config )
{
	struct sockaddr_un address;
	int one = 1;

	listen_socket = socket (PF_UNIX, SOCK_STREAM, 0);
	if (listen_socket < 0) {
        	audit_msg(LOG_ERR, "Cannot create PF_UNIX listener socket");
		return 1;
	}

	set_close_on_exec (listen_socket);
	setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
			(char *)&one, sizeof (int));

	memset (&address, 0, sizeof(address));
	address.sun_family = AF_UNIX;
        strcpy(&address.sun_path[0], config->log_file);

	/* This avoids problems if auditd needs to be restarted.  */
	setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
			(char *)&one, sizeof (int));

        // Unlink the path to the socket. We can assume this is
        // safe becase the path is located in /dev unless
        // the user changes it in the configuration file.
        // The fact the file specified in the configuration
        // is going to be unlinked will be included in the
        // README.
        if(unlink(config->log_file)) {
          audit_msg(LOG_ERR, "Could not unlink socket location (%s)",
              strerror(errno));

          return 1;
        }

	if (bind(listen_socket, (struct sockaddr *)&address, sizeof(address))){
        	audit_msg(LOG_ERR,
			"Cannot bind af_unix listener socket to location(%s)",
			strerror(errno));
		close(listen_socket);
		return 1;
	}
	
        // Put socket in nonblock mode
	int cmd = fcntl(listen_socket, F_GETFL);
	fcntl(listen_socket, F_SETFL, cmd|O_NONBLOCK);

	// don't leak the descriptor
	cmd = fcntl(listen_socket, F_GETFD);
	fcntl(listen_socket, F_SETFD, cmd|FD_CLOEXEC);

	listen(listen_socket, config->tcp_listen_queue);

	audit_msg(LOG_DEBUG, "Listening on UNIX SOCKET %s",
		config->log_file);

        // Get UID for audit
        struct passwd *userpw = NULL;
        userpw = getpwnam("audit");
        uid_t userid = -1;

        if (userpw == NULL) {
          audit_msg(LOG_ERR, "Cannot find user audit.");
        }
        else {
          userid = userpw->pw_uid;
          audit_msg(LOG_ERR, "Audit UserID is: %d", userid);
        }

        // Get GID for audit
        struct group *groupname = NULL;
        groupname = getgrnam("audit");
        gid_t groupid = -1;

        if (groupname == NULL) {
          audit_msg(LOG_ERR, "Cannot find group audit.");
        }
        else {
          groupid = groupname->gr_gid;
          audit_msg(LOG_ERR, "Audit GroupID is: %d", groupid);
        }
  
        // chown the file descriptor to be audit/audit
        if (chown(config->log_file,  userid, groupid)) {
          audit_msg(LOG_ERR, "Cannot chown af_unix socket (%s)", 
              strerror(errno));
        }
        
        // Make sure the socket is read/write (0660) by
        // the audit.audit user/grp
        if (chmod(config->log_file, AUDITD_SOCKET_MODE)) {
          audit_msg(LOG_ERR, "Cannot chmod 0660 af_unix listener socket(%s)",
              strerror(errno));
          return 1;
        }


	ev_io_init (&tcp_listen_watcher, auditd_tcp_listen_handler,
			listen_socket, EV_READ);
	ev_io_start (loop, &tcp_listen_watcher);

	use_libwrap = config->use_libwrap;

	return 0;
}

void auditd_tcp_listen_uninit ( struct ev_loop *loop )
{
#ifdef USE_GSSAPI
	OM_uint32 status;
#endif

	ev_io_stop ( loop, &tcp_listen_watcher );
	close ( listen_socket );

#ifdef USE_GSSAPI
	if (use_gss) {
		use_gss = 0;
		gss_release_cred(&status, &server_creds);
	}
#endif

	while (client_chain) {
		unsigned char ack[AUDIT_RMW_HEADER_SIZE];

		AUDIT_RMW_PACK_HEADER (ack, 0, AUDIT_RMW_TYPE_ENDING, 0, 0);
		client_ack (client_chain, ack, "");
		ev_io_stop (loop, &client_chain->io);
		close_client (client_chain);
	}
}

void auditd_tcp_listen_check_idle (struct ev_loop *loop )
{
	struct ev_tcp *ev, *next = NULL;
	int active;

	for (ev = client_chain; ev; ev = next) {
		active = ev->client_active;
		ev->client_active = 0;
		if (active)
			continue;

		audit_msg(LOG_NOTICE,
			"client %s idle too long - closing connection\n",
			sockaddr_to_addr4(&(ev->addr)));
		ev_io_stop (loop, &ev->io);
		release_client(ev);
		next = ev->next;
		free(ev);
	}
}

int dispatch_event_to_socket(const struct audit_reply *rep) {
  struct ev_tcp *ev, *next = NULL;
  int active;
  int len;
  char *msgfromparser; // must be free'd

  // audit_reply messages may contain newlines. Parse them out.
  // Candidate code for parse_removenewlines function.
  char *tmpstr = rep->message;
  while(( tmpstr = strchr(tmpstr, 0x0A)) != NULL) {
    if (tmpstr != &rep->message[rep->len-1])
      *tmpstr = ' ';
    else
      break;
  }

  // Get our parsed message
  msgfromparser = interpret_reply(rep->message, rep->len, rep->type);
  len = strlen(msgfromparser); //asprintf created string so /0 is there.

  // For each client that's connected, send them the message.
  for (ev = client_chain; ev; ev = next) {

    // New code writing the string created... will be removed when
    // SPADE parsing is rewritten
    ar_write(ev->io.fd, msgfromparser, len);

    // Old code. Saved because it'll be used when SPADE is rewritten
    // ar_write(ev->io.fd,rep->message, rep->len);

    // This is for the sake of parsing the socket output.
    ar_write(ev->io.fd, "\n\n", 2);
  }

  free(msgfromparser);

  return 0;
}
